package user

import (
	"context"

	"gitee.com/liuxuezhan/ar-platform/assets-rpc/internal/dao/model/config"
	schemaUser "gitee.com/liuxuezhan/ar-platform/assets-rpc/internal/dao/schema/user"
	"gitee.com/liuxuezhan/ar-platform/assets-rpc/pkg/xerrors"
	"gitee.com/liuxuezhan/ar-platform/assets-rpc/rpc"
	"github.com/zeromicro/go-zero/core/logx"
	"gorm.io/gorm"
)

type WalletLogModel struct {
	ctx context.Context
	db  *gorm.DB
	logx.Logger
}

func (m *WalletLogModel) getDB() *gorm.DB {
	return m.db
}

func NewWalletLogModel(ctx context.Context, db *gorm.DB) *WalletLogModel {
	return &WalletLogModel{
		ctx:    ctx,
		db:     db,
		Logger: logx.WithContext(ctx),
	}
}

// Create 创建一条钱包日志
func (m *WalletLogModel) Create(
	userWallet *schemaUser.UserWallet, // 修改后的用户钱包
	transferType int64, // 转账类型：1转入，2转出
	amount float64, // 变动金额
	typeId int64, // 变动类型
	sourceId string, // 来源ID，与和变动类型一起形成唯一值
	desc string, // 描述信息，可以为空，但最好写一下
	operatorId int64, // 操作人ID，用户端为0，管理后台为管理员ID
) (*schemaUser.UserWalletLog, error) {
	// userWallet.Balance 表示结束余额
	var balanceEnd = userWallet.Balance
	var balanceStart float64
	// 计算开始余额
	switch transferType {
	case schemaUser.TRANSFER_TYPE_IN:
		balanceStart = userWallet.Balance - amount
	case schemaUser.TRANSFER_TYPE_OUT:
		balanceStart = userWallet.Balance + amount
	default:
		// transferType类型不存在
		return nil, xerrors.ErrWalletLogTransferTypeNotExist
	}
	// 查询类型是否存在
	isExist, inoutType, err := config.NewInoutModel(m.ctx, m.db).Exists(typeId)
	// 查询错误
	if err != nil {
		return nil, err
	}
	// 类型不存在
	if !isExist {
		return nil, xerrors.ErrWalletLogTypeNotExist
	}
	// 如果desc为空，则使用typeId对应的描述
	if desc == "" {
		desc = inoutType.Name
	}
	// 制作数据
	userWalletLog := &schemaUser.UserWalletLog{
		UserId:       userWallet.UserId,
		Amount:       amount,
		TransferType: transferType,
		BalanceStart: balanceStart,
		BalanceEnd:   balanceEnd,
		TypeID:       typeId,
		TypeName:     inoutType.Name,
		SourceId:     sourceId,
		Description:  desc,
		OperatorId:   operatorId,
	}
	// 插入数据
	result := m.db.Create(userWalletLog)
	if err := result.Error; err != nil {
		return nil, err
	}
	return userWalletLog, nil
}

// List 钱包日志列表
func (m *WalletLogModel) List(req *rpc.UserWalletLogRequest) (models []schemaUser.UserWalletLog, total int64, err error) {
	tx := m.getDB().WithContext(m.ctx).Model(&schemaUser.UserWalletLog{})
	if req.Id > 0 {
		tx.Where("id = ?", req.Id)
	}
	// 筛选【UserId】
	if req.UserId > 0 {
		tx.Where("user_id = ?", req.UserId)
	}
	// 筛选【TypeId】
	if req.TypeId > 0 {
		tx.Where("type_id = ?", req.TypeId)
	}
	// 筛选【开始时间】
	if req.StartTime > 0 {
		tx.Where("created_at >= ?", req.StartTime)
	}
	// 筛选【结束时间】
	if req.EndTime > 0 {
		tx.Where("created_at <= ?", req.EndTime)
	}
	// 筛选【SourceId】
	if req.SourceId != "" {
		tx.Where("source_id = ?", req.SourceId)
	}
	if req.OperateId > 0 {
		tx.Where("operator_id = ?", req.OperateId)
	}
	if req.TransferType > 0 {
		tx.Where("transfer_type = ?", req.TransferType)
	}

	// 数据条数
	result := tx.WithContext(m.ctx).Count(&total)
	if err := result.Error; err != nil {
		return models, total, err
	}
	// 排序分页
	result = tx.WithContext(m.ctx).
		Order("created_at desc").
		Offset(int((req.Page - 1) * req.PageSize)).
		Limit(int(req.PageSize)).
		Find(&models)
	if err := result.Error; err != nil {
		return models, total, err
	}
	return
}
